package com.lz.sports.ui.checkmodel

import android.content.Context
import android.graphics.Color
import android.graphics.Rect
import android.graphics.SurfaceTexture
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.TextureView
import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import com.jeremyliao.liveeventbus.LiveEventBus
import com.lz.helper.CameraHelper
import com.lz.helper.HelperConfig
import com.lz.helper.camera.CameraParameter
import com.lz.helper.camera.CameraView
import com.lz.helper.camera.DrawHelper
import com.lz.helper.camera.DrawInfo
import com.lz.helper.face.*
import com.lz.helper.idcard.IDCardHelper
import com.lz.helper.idcard.IDCardInfo
import com.lz.library.base.BaseFragment
import com.lz.sports.BR
import com.lz.sports.LogUtils
import com.lz.sports.R
import com.lz.sports.bean.Examinee
import com.lz.sports.core.SoundHelper
import com.lz.sports.databinding.FragmFaceIdentifyBinding
import com.lz.sports.utils.ToastUtils
import com.lz.sports.vm.checkmodel.FaceIdentifyViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

//人脸识别
class FaceIdentifyFragment : BaseFragment<FaceIdentifyViewModel, FragmFaceIdentifyBinding>(),
    CameraView.PreviewCallback, TextureView.SurfaceTextureListener, CameraHelper.CameraCallback,
    IDCardHelper.IDCardCallback, FeatureRequest.Callback {

    companion object {

        val handler = Handler(Looper.getMainLooper())

        fun newInstance(type: Int, examThreshold: Float, idCardThreshold: Float): FaceIdentifyFragment {
            val fragment = FaceIdentifyFragment()
            val args = Bundle().apply {
                putInt("type", type)
                putFloat("examThreshold", examThreshold)
                putFloat("idCardThreshold", idCardThreshold)
            }
            fragment.arguments = args
            return fragment
        }
    }

    private val parameter = CameraParameter.def()

    private var drawHelper: DrawHelper? = null

    //验证类型
    private var type: Int = 0

    //阀值
    private var examThreshold: Float = 0f
    private var idCardThreshold: Float = 0f


    override fun getLayoutRes(): Int = R.layout.fragm_face_identify

    override fun getVMVariableId(): Int = BR.vm

    private var scaleX = 0f
    private var scaleY = 0f

    private var hasResume = false

    private val helper by lazy {
        val w: Int
        val h: Int
        //如果流数据做了直角旋转，则必然导致宽高互换
        //如果流数据做了直角旋转，则必然导致宽高互换
        if (parameter.rotation == 90 || parameter.rotation == 270) {
            w = parameter.resolution[1]
            h = parameter.resolution[0]
        } else {
            w = parameter.resolution[0]
            h = parameter.resolution[1]
        }

        CameraHelper(w, h, this)
    }

    private val cardHelper: IDCardHelper by lazy { IDCardHelper(requireContext(), true, this) }

    private val soundHelper by lazy { SoundHelper() }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        type = arguments!!.getInt("type")
        examThreshold = arguments!!.getFloat("examThreshold")
        idCardThreshold = arguments!!.getFloat("idCardThreshold")
        soundHelper.init(intArrayOf(com.lz.helper.R.raw.idcard_read, com.lz.helper.R.raw.idcard_success))
    }

    override fun initData(savedState: Bundle?) {
        initPreview()
        cardHelper.start()
    }

    override fun onResume() {
        super.onResume()
        hasResume = true
        binding.cvCamera.openCamera()
        helper.restart()
        cardHelper.restart()
        lifecycleScope.launch {
            delay(500)
            soundHelper.play(0)
        }
    }

    override fun onPause() {
        super.onPause()
        hasResume = false
        binding.cvCamera.releaseCamera()
        helper.pause()
        cardHelper.pause()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        helper.quit()
        cardHelper.quit()
        soundHelper.release()
    }

    private fun initPreview() {
        if (HelperConfig.isLYTDFlat()) parameter.setBackCamera() else parameter.setFrontCamera()
        binding.cvCamera.setParameter(parameter)
        binding.cvCamera.setPreviewCallback(this)
        binding.cvCamera.surfaceTextureListener = this
        helper.start()
    }

    override fun onPreviewFrame(data: ByteArray, w: Int, h: Int) {
        helper.pushNvData(data)
    }

    override fun onSurfaceTextureAvailable(surface: SurfaceTexture, w: Int, h: Int) {
        scaleX = binding.cvCamera.width / 480f
        scaleY = binding.cvCamera.height / 640f
        drawHelper = DrawHelper(
            w, h, binding.cvCamera.width, binding.cvCamera.height,
            0, parameter.cameraId, false, false, false
        )
        binding.cvCamera.openCamera()
    }

    override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, w: Int, h: Int) {
    }

    override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean = false

    override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
    }

    override fun onDetectSuccess(detect: IntArray) {
        setDrawInfo(detect)
    }

    override fun onCameraError(status: Int) {
        if (status == CameraOperator.ERR_DETECT) {
            setDrawInfoNull()
        }
    }

    //检测到人脸页面上框出来
    private fun setDrawInfo(faceInfo: IntArray) {
        if (hasResume) {
//            LogUtils.i("drawInfo...")
            drawInfo.rect.set(
                (faceInfo[1] * scaleX).toInt(), (faceInfo[2] * scaleY).toInt(),
                (faceInfo[3] * scaleX).toInt(), (faceInfo[4] * scaleY).toInt()
            )
            drawHelper?.draw(binding.fvCamera, drawInfo)
        }
    }

    private val drawInfo = DrawInfo(Rect(), Color.GREEN, "")

    private fun setDrawInfoNull() {
        if (hasResume) {
            drawInfo.rect.set(0, 0, 0, 0)
            drawHelper?.draw(binding.fvCamera, drawInfo)
        }
    }

    override fun onCardResult(idCardInfo: IDCardInfo) {
        if (isFacing && !hasResume) return
        lifecycleScope.launch {
            soundHelper.play(1)
            val job = async(Dispatchers.Default) {
                LogUtils.i("find  ${idCardInfo.num}")
                findExaminee(idCardInfo)
            }
            val examinee = job.await()
            if (examinee != null) {
                currentExaminee = examinee
                faceExaminee(examinee, idCardInfo)
            }
        }
    }

    private fun findExaminee(idCardInfo: IDCardInfo): Examinee? {
        if (activity is ExamineeFinder && !activity!!.isFinishing)
            return (context as ExamineeFinder).findExamineeByIDCardInfo(idCardInfo)
        if (parentFragment is ExamineeFinder && parentFragment!!.isResumed)
            return (parentFragment as ExamineeFinder).findExamineeByIDCardInfo(idCardInfo)
        return null
    }

    override fun onCardError(err: Int) {
    }

    private fun faceExaminee(examinee: Examinee, idCardInfo: IDCardInfo) {
        val examBitmap = loadBitmap(examinee.examPhotoFile())
        if (examBitmap == null) {
            ToastUtils.showMyToast(R.string.examineePhotoNone, Toast.LENGTH_SHORT)
            return
        }
        val idCardBitmap = idCardInfo.photoBitmap()
        if (idCardBitmap == null) {
            ToastUtils.showMyToast(R.string.idCardPhotoNone, Toast.LENGTH_SHORT)
            return
        }
        val examParams = FeatureParams(examBitmap, examThreshold)
        val idCardParams = FeatureParams(idCardBitmap, idCardThreshold)

        val request = when (type) {
            1 -> SingleRequest(type, null, examParams, handler, this)
            2 -> SingleRequest(type, idCardParams, null, handler, this)
            7 -> DoubleOrRequest(type, idCardParams, examParams, handler, this)
            12 -> DoubleAndRequest(type, idCardParams, examParams, handler, this)
            else -> null
        }
        if (request == null) {
            ToastUtils.showMyToast(R.string.faceIdentifySupport, Toast.LENGTH_SHORT)
            return
        }
        if (helper.pushFeatureRequest(request)) {
            isFacing = true
            ToastUtils.showMyToast("识别中...", Toast.LENGTH_SHORT)
        }
    }

    private var isFacing = false

    private var currentExaminee: Examinee? = null

    override fun onFeatureError(type: Int, err: Int) {
        isFacing = false
        ToastUtils.showMyToast(R.string.faceIdentifyFail, Toast.LENGTH_SHORT)

        lifecycleScope.launch {
            soundHelper.play(0)
        }
    }

    override fun onFeatureSuccess(
        type: Int,
        nvData: ByteArray,
        w: Int,
        h: Int,
        photoParams: FeatureParams?,
        examParams: FeatureParams?
    ) {
        isFacing = false
        LiveEventBus.get("FaceIdentify", FeatureResult::class.java)
            .post(FeatureResult(type, nvData, w, h, currentExaminee!!, photoParams, examParams))
        ToastUtils.showMyToast(R.string.faceIdentifySuccess, Toast.LENGTH_SHORT)
    }
}